#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#include "standard.h"

int ouvrirCommunication(int appelant, int appele) {
	
	int appeleConnu = 0;	// variable indiquant si le telephone appele est abonne
	int res = 99;		// variable de retour de la fonction
	int i;

	printf("[Standard] Tentative de communication entre %d et %d\n", appelant, appele);

	// Verifier si l'appele est abonne	
	for(i=0;i<NB_FIXES;i++) {
		if(fixesAbonnes[i].numero == appele) {
			appeleConnu = 1;
			printf("[Standard] Le correspondant (telephone %d) à été localisé\n", appele);
		}
	}
	// Sinon retourner -5
	if(appeleConnu != 1) {
		res = -5;
	}
	// On teste si le repondeur est activé
	else if(fixesAbonnes[appele].repondeur == 1) {
		res = -3;
		fixesAbonnes[appele].numAppelManque = appelant;
		// fixesAbonnes[appele].dateAppelManque = ? ;
	}
	// TODO : tester si le telephone est occupé
	// Sinon on lance la conversation
	else {
		printf("\n");
		// Créer un thread de communication
		res = demarrerCommunication(appelant, appele);
	}

	return res;
}


void activerRepondeurTel(int monNum) {
	fixesAbonnes[monNum].repondeur = 1;
	printf("[telephone %d] Repondeur activé.\n", monNum);
}

void desactiverRepondeurTel(int monNum) {
	fixesAbonnes[monNum].repondeur = 0;
	printf("[telephone %d] Repondeur désactivé.\n", monNum);
	printf("[telephone %d] Dernier appel manque de telephone %d.\n", monNum, fixesAbonnes[monNum].numAppelManque);
}


void abonnerFixe(int numero) {
	fixesAbonnes[numero].numero = numero;

	fixesAbonnes[numero].repondeur = 0;
	fixesAbonnes[numero].numAppelManque = 0;
	printf("[telephone %d] Je suis dorénavant abonné.\n", numero);
}

void* communication(void* args) {
	threadsArgs* arguments = (threadsArgs*) args;

	int cpt = 0;		// Chaque conversation se fait en 10 echanges

	printf("[Standard] Thread de communication démarré.\n");

	// Lock du mutex secondaire, pour ne pas lire tant qu'il n'y a rien
	pthread_mutex_lock(&tabMutexMess2[(*arguments).indiceUtilise]);

	// Transmet les infos de la conversation à l'autre telephone
	configReceiver((*arguments).receiver, (*arguments).indiceUtilise, (*arguments).sender);

	printf("[Standard] Conversation lancée sur canal %d\n", (*arguments).indiceUtilise);

	// Lance la converation entre les 2 telephones
	lancerConversation((*arguments).sender, (*arguments).receiver);

	while(cpt < 10) {
		// Attente du depos d'un message
		pthread_mutex_lock(&tabMutexMess2[(*arguments).indiceUtilise]);

		sleep(1);

		// Previens les telephone que le message est lu
		pthread_mutex_unlock(&tabMutexMess[(*arguments).indiceUtilise]);

		cpt++;
	}

	printf("[Standard] Conversation terminée sur canal %d\n", (*arguments).indiceUtilise);
}

int demarrerCommunication(int appelant, int appele) {

	pthread_t idThrd;
	int i = 0;		// Indice du while
	int trouve = 0;		// Indique si une place a été trouvée dans le pool de messages

	// Preparation des arguments du thread
	threadsArgs* args;
	(*args).sender = appelant;
	(*args).receiver = appele;

	// On cherche quelle case tu tableau des messages on va pouvoir utiliser pour communiquer
	// On protège l'operation par un mutex pour empécher 2 threads de choisir la même case
	pthread_mutex_lock(&mutexRecherche);
	while( (trouve==0) && (i<NB_FIXES) ) {
		if(messagePool[i].sender == 0) {
			trouve = 1;
			(*args).indiceUtilise = i;
			messagePool[i].sender = (*args).sender;
			messagePool[i].receiver = (*args).receiver;
		}
		i++;
	}
	pthread_mutex_unlock(&mutexRecherche);

	// Creation du thread de communication
	if(pthread_create(&idThrd, NULL, communication, (void*) args) == -1) {
		perror("Erreur de creation d'un thread de communication\n");
	}
	// On détache le thread pour qu'il se termine tout seul
	pthread_detach(idThrd);

	// On retourne la valeur du canal utilisé pour la communication
	return (*args).indiceUtilise = i;
}

// Ces 2 fonctions sont utilisées par les telephones (ADA) pour manipuler
// les mutex dont ils peuvent avoir besoin
void unlockMutex2(int indice) {
	pthread_mutex_unlock(&tabMutexMess2[indice]);
}

void lockMutex(int indice) {
	pthread_mutex_lock(&tabMutexMess[indice]);
}
